package com.kaifamiao.jdbc;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
import java.util.logging.Logger;

public class DbHelper {

    private static final Logger LOGGER = Logger.getAnonymousLogger();

    private static final String CONNECT = "jdbc.connect" ;
    private static final String PREFIX = "jdbc.connection." ;
    private static final String NAME = "jdbc.properties" ;
    private static final Properties PROPS = new Properties();

    private static String driver ; // 驱动类
    private static String url ; // URL
    private static String username ; // 数据库用户名
    private static String password ; // 数据库密码

    static {
        read(); // 读取配置文件
        configure(); // 从 PROPS 中获取相应的值
    }

    /**
     * 读取配置文件中的内容
     */
    private static void read(){
        try {
            // 获取用于读取类路径根目录下指定文件的字节输入流
            InputStream in = DbHelper.class.getResourceAsStream("/" + NAME);
            // 加载字节输入流中的内容到 Properties 集合中
            PROPS.load(in);
            in.close();
        } catch ( IOException e ) {
            e.printStackTrace();
        }
    }

    /**
     * 从 PROPS 中获取相应的数据库连接信息
     */
    private static void configure(){
        // 首先确定连接哪个数据库
        String dbName = PROPS.getProperty( CONNECT );
        driver = PROPS.getProperty( PREFIX + dbName + ".driver" );
        url = PROPS.getProperty( PREFIX + dbName + ".url" );
        username = PROPS.getProperty( PREFIX + dbName + ".username" );
        password = PROPS.getProperty( PREFIX + dbName + ".password" );
    }

    /**
     * 加载驱动类
     */
    public void load(){
        try {
            Class.forName( driver );
            LOGGER.info( "驱动" + driver + "加载成功" );
        } catch (ClassNotFoundException e) {
            LOGGER.info( "驱动" + driver + "加载失败: " + e.getMessage() );
        }
    }

    /**
     * 建立数据库连接
     * @return 返回数据库连接
     */
    public Connection connect(){
        try {
            Connection conn = DriverManager.getConnection(url, username, password);
            LOGGER.info( "成功连接到" + url + "" );
            return conn ;
        } catch ( SQLException e ) {
            LOGGER.info( "连接" + url + "时发生错误: " + e.getMessage() );
            return null ;
        }
    }

    /**
     * 处理结果集中的的单行数据
     * @param rs 被处理的结果集
     */
    public void processRow( ResultSet rs , DbRowHandler h ) throws SQLException{
        h.handle(rs);
    }

    /**
     * 处理结果集
     * @param rs 被处理的结果集
     */
    public void process( ResultSet rs ){
        // 输出不是目的，只是这里还是低级阶段，所以就用来输出了
        if( rs == null ) {
            throw  new IllegalStateException( "结果集不可以为空哦" );
        }

        // 声明一个用来记录列数的变量
        int count = 0 ;

        try {
            // 获取结果集元数据
            ResultSetMetaData rsmd = rs.getMetaData();
            // 获得结果集中包含的列数
            count = rsmd.getColumnCount();
            // 输出结果集中所包含的各个列的列名
            for( int i = 1 ; i <= count ; i++ ){
                String label = rsmd.getColumnLabel( i );
                System.out.print( label );
                System.out.print( '\t' );
            }
            System.out.println();
        } catch (SQLException e) {
            LOGGER.info( "获取结果集元数据失败: " + e.getMessage() );
        }

        try {
            // 输出结果集中的每行数据
            while (rs.next()) {
                // 根据列的索引依次获取各个列的值
                for( int i = 1 ; i <= count ; i++ ) {
                    Object value = rs.getObject( i );
                    System.out.print( value );
                    System.out.print( '\t' );
                }
                System.out.println();
            }
        } catch ( SQLException e ) {
            LOGGER.info( "遍历结果集时发生错误: " + e.getMessage() );
        }

    }

    /**
     * 释放给定的资源
     * 因为 Connection 、Statement 、ResultSet 都继承了 AutoCloseable 接口
     * 所以参数就是 java.lang.AutoCloseable 类型 ( JDK 1.7 新增的接口 )
     */
    public void release( AutoCloseable ac ){
        if( ac != null ) {
            try {
                ac.close();
            } catch ( Exception e ) {
                LOGGER.info( "释放资源时发生错误: " + e.getMessage() );
            }
        }
    }

}
